#include "MyApp.h"


MyApp::MyApp(HINSTANCE hInstance)
	:D3DApp(hInstance)
	,m_EyePos(D3DXVECTOR3(0.0f,2.0f,-2.0f))
	//,crate(&m_EyePos,&m_matView,&m_matProj)
{
	D3DXMatrixIdentity(&m_matView);
}


MyApp::~MyApp(void)
{
	m_TerrainManager.Destory();
}

void MyApp::initApp()
{
	D3DApp::initApp();

//////////////////Resource Manager////////////////////////////////////////////////////////
	ResourcesManager::Init(md3dDevice);

/////////////////Scene Manager/////////////////////////////////////////////////////////
	m_SceneMgr.Init(md3dDevice);

//////////////////Terrain Manager////////////////////////////////////////////////////////
	m_TerrainManager.Init(md3dDevice);

//////////////////Message System//////////////////////////////////////////
	MessageQueryer::Instance()->Init();

//////////////////////////////////////////////////////////////////////////
	SceneTest();

	TerrainTest();
}

void MyApp::onResize()
{
	D3DApp::onResize();

	float aspect = (float)mClientWidth/mClientHeight;
	D3DXMatrixPerspectiveFovLH(&m_matProj, 0.25f*PI, aspect, 0.5f, 1000.0f);
	GlobalMessage::Instance()->SetProjMatrix(m_matProj);

	m_SceneMgr.SetProjMatrix(m_matProj);
}

void MyApp::updateScene( float dt )
{
	D3DApp::updateScene(dt);

	//set the global message time from last frame
	GlobalMessage::Instance()->SetTimeFromLastFrame(dt);

	//dispatch message
	MessageDispatcher::Instance()->DispatchKeyboardDownMessage();


	//m_SceneMgr.SetViewMatrix(m_Camera.GetView());
	m_SceneMgr.UpdateScene();

}

void MyApp::drawScene()
{
	D3DApp::drawScene();

	md3dDevice->OMSetDepthStencilState(0,0);
	float blendFactor[] = {0.0f, 0.0f, 0.0f, 0.0f};
	md3dDevice->OMSetBlendState(0, blendFactor, 0xffffffff);
///////////////Rendering Terrain///////////////////////////////////////////////////////////
	m_TerrainManager.Rendering();

///////////////Rendering Scene///////////////////////////////////////////////////////////
	m_SceneMgr.RenderOneFrame();

//////////////////////////////////////////////////////////////////////////
	RECT R = {5, 5, 0, 0};
	md3dDevice->RSSetState(0);
	mFont->DrawText(0, mFrameStats.c_str(), -1, &R, DT_NOCLIP, BLACK);

	mSwapChain->Present(0, 0);
}

void MyApp::SceneTest()
{
	Node* crateNode = m_SceneMgr.CreateNode("crate");


	ID3D10ShaderResourceView* m_pDiffuseMapRV;
	//create the texture resource view
	//HR( D3DX10CreateShaderResourceViewFromFile(md3dDevice,L"WoodCrate01.dds"
	//	,0,0,&m_pDiffuseMapRV,0) );
	m_pDiffuseMapRV = ResourcesManager::Instance()->GetTexture("WoodCrate01.dds");

	crateNode->AttachTexture(m_pDiffuseMapRV);

	int m_iNumVertices = 24;
	int m_iNumFaces    = 12; // 2 per quad

	D3DXMATRIX t;
	D3DXMatrixIdentity(&t);
	//crateNode->SetWorldMatrix(t);

	// Create vertex buffer
	Vertex v[24];

	// Fill in the front face vertex data.
	v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[1] = Vertex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[2] = Vertex( 1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	v[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

	// Fill in the back face vertex data.
	v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f);
	v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);
	v[6] = Vertex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
	v[7] = Vertex(-1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f);

	// Fill in the top face vertex data.
	v[8]  = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[9]  = Vertex(-1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
	v[10] = Vertex( 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
	v[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);

	// Fill in the bottom face vertex data.
	v[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f);
	v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f);
	v[14] = Vertex( 1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
	v[15] = Vertex(-1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);

	// Fill in the left face vertex data.
	v[16] = Vertex(-1.0f, -1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
	v[17] = Vertex(-1.0f,  1.0f,  1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
	v[18] = Vertex(-1.0f,  1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
	v[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);

	// Fill in the right face vertex data.
	v[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
	v[21] = Vertex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f);
	v[22] = Vertex( 1.0f,  1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f);
	v[23] = Vertex( 1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);


	ID3D10Buffer*				m_pVB;
	ID3D10Buffer*				m_pIB;

	D3D10_BUFFER_DESC vbd;
	vbd.Usage = D3D10_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(Vertex) * m_iNumVertices;
	vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	D3D10_SUBRESOURCE_DATA vinitData;
	vinitData.pSysMem = v;
	HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &m_pVB));

	crateNode->SetVertexBuffer(m_pVB,24);

	// Create the index buffer

	DWORD i[36];

	// Fill in the front face index data
	i[0] = 0; i[1] = 1; i[2] = 2;
	i[3] = 0; i[4] = 2; i[5] = 3;

	// Fill in the back face index data
	i[6] = 4; i[7]  = 5; i[8]  = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	// Fill in the top face index data
	i[12] = 8; i[13] =  9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	// Fill in the bottom face index data
	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;

	// Fill in the left face index data
	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;

	// Fill in the right face index data
	i[30] = 20; i[31] = 21; i[32] = 22;
	i[33] = 20; i[34] = 22; i[35] = 23;

	D3D10_BUFFER_DESC ibd;
	ibd.Usage = D3D10_USAGE_IMMUTABLE;
	ibd.ByteWidth = sizeof(DWORD) * m_iNumFaces*3;
	ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	D3D10_SUBRESOURCE_DATA iinitData;
	iinitData.pSysMem = i;
	HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &m_pIB));

	crateNode->SetIndexBuffer(m_pIB,36);

	m_SceneMgr.GetRootNode()->AddChildNode(crateNode);
}

LRESULT MyApp::msgProc( UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
////////////////////////Mouse Message////////////////////////////////
	case WM_MOUSEMOVE:
		MessageDispatcher::Instance()->DispatchMouseMessage(MMsg_Move,lParam);
		return 0;

	case WM_LBUTTONDOWN:
		MessageDispatcher::Instance()->DispatchMouseMessage(MMsg_LeftButtonDown,lParam);
		return 0;

	case WM_LBUTTONUP:
		MessageDispatcher::Instance()->DispatchMouseMessage(MMsg_LeftButtonUp,lParam);
		return 0;

	case WM_RBUTTONDOWN:
		MessageDispatcher::Instance()->DispatchMouseMessage(MMsg_RightButtonDown,lParam);
		return 0;

	case WM_RBUTTONUP:
		MessageDispatcher::Instance()->DispatchMouseMessage(MMsg_RightButtonUp,lParam);
		return 0;
////////////////////////Keyboard Message//////////////////////////////////
	case WM_CHAR:
		MessageDispatcher::Instance()->DispatchKeyboardMessage(wParam);
		return 0;
//////////////////////////////////////////////////////////////////////////
	}

	return D3DApp::msgProc(msg, wParam, lParam);
}

void MyApp::TerrainTest()
{
	m_TerrainManager.SetDirectionToSun(-D3DXVECTOR3(0.707f, -0.707f, 0.0f));

	TerrainInformation info;
	info.HeightmapFilename = "coastMountain513.raw";
	info.LayerMapFilename0 = "grass.dds";
	info.LayerMapFilename1 = "lightdirt.dds";
	info.LayerMapFilename2 = "darkdirt.dds";
	info.LayerMapFilename3 = "stone.dds";
	info.LayerMapFilename4 = "snow.dds";
	info.BlendMapFilename  = "blend.dds";

	info.HeightScale  = 0.35f;
	info.HeightOffset = -20.0f;
	info.NumRows      = 513;
	info.NumCols      = 513;
	info.CellSpacing  = 1.0f;

	m_TerrainManager.AddTerrain(info,D3DXVECTOR3(0,0,0));
}
